<?php
/**
*  Class that generate a NHibernateMVC project
*  @filesource
 * @author			Jaydson Gomes
 * @author			Filipe Pamplona
 * @copyright		Copyright <2009> TheWebMind.org
 * @package			NHibernateMVC
 * @version			0.1
*/
	class NHibernateMVC extends Module implements module_interface
	{
		private $project;
		private $knowledge;
		private $structure;
		
		/**
		* Get who references to the table
		*@param Object 	$tableObject - The Table
		*@return Array
		*/
		public function getReferences($tableObject){
			$Arrayreferenceds = $tableObject->refered;
			$referenceds = Array();						
			for($i=0;$i<sizeof($Arrayreferenceds);$i++){
				$referenceds[$i] = explode("|",$Arrayreferenceds[$i]);
				$referenceds[$i] = $referenceds[$i][1];
			}
			return $referenceds;
		}
		
		/**
		* Get foreign keys
		*@param Object 	$tableObject - The Table
		*@return Array
		*/
		public function getForeignKeys($tableObject){
			$foreignKeys = $tableObject->foreignKeys;
			$ret= Array();
			for($i=0;$i<sizeof($foreignKeys);$i++){
				$ret[$foreignKeys[$i][0]]= $foreignKeys[$i][1];
			}
			return $ret;
		}
		
		/**
		* Get primary keys
		*@param Object 	$tableObject - The Table
		*@return String
		*/
		public function getPrimaryKey($tableObject){
			$attr = $tableObject->attributes;
			reset($attr);
			return key($attr);
		}
		
		/**
		* Prepare the name of Class
		*@param String 	$name - The name of class
		*@return String
		*/
		public function prepareClassName($name){
			$tempName = str_replace('_',' ',$name);
			$tempName = ucwords($tempName);
			return str_replace(' ','',$tempName);
		}
		
		/**
		* Prepare the name of Label
		*@param String 	$name - The name of class
		*@return String
		*/
		public function prepareLabelName($name){
			return ucwords(str_replace("_"," ",$name));
		}
		
		/**
		* Prepare the folder name
		*@param String 	$name - The name of class
		*@return String
		*/
		public function prepareFolderName($name){
			//return strtolower(str_replace("_","-",$name));
			$tempName = str_replace('_',' ',$name);
			$tempName = ucwords($tempName);
			return str_replace(' ','',$tempName);
		}
		
				
		/**
		* Prepare name to show on select options
		*@param String 	$name - The name of table
		*@return String
		*/
		public function getOptionLabel($table){	
			$table = $this->knowledge->tables[$table];
			reset($table->attributes);
			$temp;
			$counter=0;
			while($cur = current($table->attributes)){
				if($counter<2){
					$temp = $cur->name;
				}
				switch($cur->type){
					case 'string':
					case 'char':
					case 'varchar':
					case 'text':
						return $cur->name;
					break;
				} 
				next($table->attributes);
				$counter++;
			}
			return $temp;
		}
		
		/**
		*Create a Class comment
		*@param Array 	$commentLines - An array with n lines that you want to comment
		*@param int 		$tabs A number that define how much tabs have in the comment
		*@return String
		*/
		public function createComment($commentLines,$tabs=null){
			$tabs = $tabs != null ? $tabs : 0;
			$tab=$this->setTabText($tabs);
			$c = $tab."/**\n";
			for($i=0;$i<sizeof($commentLines);$i++){
				$c.= $i==sizeof($commentLines) ? $tab."* ".$commentLines[$i] : $tab."* ".$commentLines[$i]."\n";
			}
			$c.= $tab."*/\n";
			return $c;
		}
		
		/**
		*Get a C# type pattern
		*@param String $t Mind type
		*@return String
		*/
		public function getDotNetType($t){
			$type = '';
			switch($t){
				case 'varchar':
				case 'text':
					$type = 'string';
				break;
				case 'date':
					$type = 'DateTime';
				break;
				case 'integer':
				case 'bigint':
				case 'smallint':
				case 'int':
					$type = 'int';
				break;
				case 'boolean':
					$type = 'boolean';
				break;
			}
			return $type;
		}
		
		/**
		* Create Models
		*@param Table 	$tableObject - Mind Table Object, that contais all knowledge
		*@return String
		*/
		public function models(&$tableObject){
			$attributes = $tableObject->attributes;
			$referenceds = $this->getReferences($tableObject);
			$pk = $this->getPrimaryKey($tableObject);
			$fks = $this->getForeignKeys($tableObject);
			$name = $this->prepareClassName($tableObject->name);
			$template = $this->fw->getContent("structure/project_name/Core/Domain/Model/template.cs");
			reset($attributes);
			$attrs = "";
			while($cur = current($attributes)){
				$attrs.= $this->setTabText(2)."public virtual ".$this->getDotNetType($cur->type)." ".$cur->name." { get; set;} \n";
				next($attributes);
			}
			$content = str_replace("#METODOS#",$attrs,$template);
			$content = str_replace("#TABELA#",$name,$content);
			
			$attrsRefereds = '';
			if(sizeof($referenceds)>0){
				for($i=0;$i<sizeof($referenceds);$i++){
					$attrsRefereds = $this->setTabText(2).'public virtual IList<' . $this->prepareClassName($referenceds[$i]).'> '.$this->prepareClassName($referenceds[$i]). 'List { get; set;}';
					$attrsRefereds.="\n";
				}
			}
			$content = str_replace("#METODOSDINAMICOS#",$attrsRefereds,$content);
			
			$attrsFks = '';
			if(sizeof($fks) > 0){
				foreach($fks as $fk){
					$attrsFks.= $this->setTabText(2).'public virtual '. $this->prepareClassName($fk). ' '. $fk. '{ get; set;}';
					$attrsFks .= "\n";
				}
			}
			$content = str_replace("#METODOSFKS#",$attrsFks,$content);			
			
			return $content;
		}
		
		/**
		* Create Repositories
		*@param Table 	$tableObject - Mind Table Object, that contais all knowledge
		*@return String
		*/
		public function repositories(&$tableObject){
			$name = $this->prepareClassName($tableObject->name);
			$template = $this->fw->getContent("structure/project_name/Core/Domain/Repositories/template.cs");
			$content = str_replace("#TABELA#",$name,$template);
			$pk = $this->getPrimaryKey($tableObject);
			$content = str_replace("#CHAVEPRIMARIA#",$pk,$content);
			
			return $content;
		}
		
		/**
		* Create Mappings
		*@param Table 	$tableObject - Mind Table Object, that contais all knowledge
		*@return String
		*/
		public function mappings(&$tableObject){
			$attributes = $tableObject->attributes;
			$referenceds = $this->getReferences($tableObject);
			$pk = $this->getPrimaryKey($tableObject);
			$fks = $this->getForeignKeys($tableObject);
			$name = $this->prepareClassName($tableObject->name);
			$template = $this->fw->getContent("structure/project_name/Infrastructure/DataAccess/Mappings/template.xml");
			reset($attributes);
			$attrs = "";
			while($cur = current($attributes)){
				if($cur->name != $pk){
					$length = $cur->size == 0 ? 500 : $cur->size;
					$attrs.= '      <property name="'.$cur->name.'" length="'.$length.'"/>';
					$attrs.= "\n";
				}
				next($attributes);
			}
			$content = str_replace("#PROPRIEDADES#",$attrs,$template);
			$content = str_replace("#TABELA#",$name,$content);
			$content = str_replace("#CHAVEPRIMARIA#",$pk,$content);
			
			$bags = '';
			if(sizeof($referenceds)>0){
				for($i=0;$i<sizeof($referenceds);$i++){
					$bags = '
      <bag name="'.$this->prepareClassName($referenceds[$i]).'List" table="'.$referenceds[$i].'" lazy="false" >
        <key column="'.$pk.'" ></key>
        <one-to-many class="'.$name.'" />
      </bag>';
					$bags.="\n";
				}
			}
			$content = str_replace("#BAGS#",$bags,$content);

			$attrsFks = '';
			if(sizeof($fks) > 0){
				foreach($fks as $fk){
					$attrsFks.= $this->setTabText(1).'<many-to-one name="'.$fk.'" column="fk_'.$fk.'" class="'.$this->prepareClassName($fk).'" />';
					$attrsFks .= "\n";
				}
			}
			$content = str_replace("#METODOSFKS#",$attrsFks,$content);
			return $content;
		}
		
		/**
		* Tells mind what the structure to copy
		*@return String
		*/
		public function getStructure(){
			return $this->structure;
		}
		
		/**
		*Method Called for each table
		*@param Table 	$tableObject - Mind Table Object, that contais all knowledge
		*@return void
		*/
		public function applyCRUD($tableObject){
			// Models
			$this->fw->mkFile('project_name/Core/Domain/Model/'
							  .$this->prepareClassName($tableObject->name).'.cs',
							  $this->models($tableObject));
							  
			//Repositories
			$this->fw->mkFile('project_name/Core/Domain/Repositories/'
							  .$this->prepareClassName($tableObject->name).'Repository.cs',
							  $this->repositories($tableObject));
			
			//Mappings
			$this->fw->mkFile('project_name/Infrastructure/DataAccess/Mappings/'
							  .$this->prepareClassName($tableObject->name).'.hbm.xml',
							  $this->mappings($tableObject));
		}
		
		/**
		* Method executed when module start
		*/
		public function onStart(){
		}
		
		/**
		* Override Module.onFinish
		* Method executed when module start
		*/
		public function onFinish(){
			// Renames the root dir
			$this->fw->rename('project_name',$this->project->name);
		}
		
		/**
		* Override Module.callExtra
		* Call extra function
		*/
		public function callExtra(){
			
		}
		
		/**
		* Construct
		*/
		public function __construct($project){
			GLOBAL $_FW;
			$this->fw= $_FW;
			$this->structure= 'structure'; // tells Mind what is the structure directory to be based on
			$this->project = $project;
			$this->knowledge= $project->knowledge;
		}
	}
?>
